/* -----------------------------------------------------------------------
 * Random testing of Adventurer Card
 *
 * -----------------------------------------------------------------------
 */

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"
#include <stdlib.h>
#include <time.h>

// set NOISY_TEST to 0 to remove printfs from output
#define NOISY_TEST 1

void randomTestAdventurer() {
    //Game setup
    int i, j;
    int seed = 1000;
    int numPlayer = 2;
    int card = adventurer;
    int k[10] = {adventurer, council_room, feast, gardens, mine
               , remodel, smithy, village, baron, great_hall};
    int allCards[17] = {adventurer, council_room, feast, gardens, mine
               , remodel, smithy, village, baron, great_hall, copper, silver, gold, curse, estate, duchy, province};
    struct gameState G;
    struct gameState Gcopy;
    int testHandCount;
    int testDeckCount;
    int testDiscardCount;
    int testCoin;
    int p = 0;

    int randomTests = 5000;

    printf ("Random testing playing 'adventurer':\n");

    for (i = 0; i < randomTests; i++) {
        initializeGame(numPlayer, k, seed, &G);
        //Need to randomize size and content of deck, content and size of player's hands
        if (i % 100 == 0)
            testHandCount = (rand() % MAX_HAND) + 1; //Random size of hand using max hand size
        else
            testHandCount = (rand() % 10) + 1; //Random size of hand between 1 and 10, much more realistic
        testDeckCount = (rand() % MAX_DECK); //Random size of deck between 0 - max deck size
        testDiscardCount = (rand() % MAX_DECK) + 2; //Include a discard pile in case shuffle needed
                                                //*****+2 included for mandatory coppers so we have a valid test case
        G.handCount[p] = testHandCount;
        G.deckCount[p] = testDeckCount;
        G.discardCount[p] = testDiscardCount;

        //Set random cards in hand and deck
        for (j = 0; j < testHandCount; j++) {
            int randCardNum = (rand() % 17);
            G.hand[p][j] = allCards[randCardNum];
        }
        for (j = 0; j < testDeckCount; j++) {
            int randCardNum = (rand() % 17);
            G.deck[p][j] = allCards[randCardNum];
        }
        for (j = 0; j < testDiscardCount; j++) {
            int randCardNum = (rand() % 17);
            G.discard[p][j] = allCards[randCardNum];
        }

        //Put the adventurer card in the hand
        G.hand[p][0] = adventurer;
        //Put two copper into the discard pile
        G.discard[p][0] = copper;
        G.discard[p][1] = copper;

        //copy of gamestate to test with
        memcpy(&Gcopy, &G, sizeof(G));

        //Set coincount
        updateCoins(p, &G, 0);
        testCoin = G.coins;

#if (NOISY_TEST == 1)    
    printf("Before playing adventurer, player has %d coin(s), %d deckcards, %d discardCards, %d handCards. %d,%d,%d,%d expected.\n", 
        G.coins, G.deckCount[p], G.discardCount[p], G.handCount[p], testCoin, testDeckCount, testDiscardCount, testHandCount);

#endif
    assert(G.coins == testCoin);
    assert(G.deckCount[p] == testDeckCount);
    assert(G.discardCount[p] == testDiscardCount);
    assert(G.handCount[p] == testHandCount);

        //Set variables for testing adventurer
        int treasureFound = 0;
        int skippedCards = 0;
        //int tbDiscarded[MAX_HAND];

        //Get two treasure cards from the deck
        for (j = testDeckCount; j > 0; j--) {
            drawCard(p, &Gcopy);
            int cardDrawn = Gcopy.hand[p][Gcopy.handCount[p]-1];
            if (cardDrawn == copper){
                treasureFound++;
                testCoin += 1;
                testHandCount++;
            }
            else if (cardDrawn == silver){
                treasureFound++;
                testCoin += 2;
                testHandCount++;
            }
            else if (cardDrawn == gold){
                treasureFound++;
                testCoin += 3;
                testHandCount++;
            }
            else {
               // tbDiscarded[skippedCards] = cardDrawn;
                Gcopy.handCount[p]--;
                skippedCards++;
            }
                
            if (treasureFound == 2)
                break;
        }
        //printf("%d treasures\n", treasureFound); 
        //only if the deck doesn't contain enough treasures, go through discard pile
        if (treasureFound < 2) {
            testDeckCount = testDiscardCount;
            printf("%d treasureFound\n", treasureFound);
            printf("%d pile, %d discard\n", Gcopy.deckCount[p], Gcopy.discardCount[p]);
            //testDeckCount = testDeckCount + testDiscardCount - treasureFound - skippedCards
            testDiscardCount = 0; //Will be in line with test case once drawCard() is called

            for (j = testDeckCount; j > 0; j--) {
                drawCard(p, &Gcopy);
                //printf("%d pile, %d discard, %d skipped", testDeckCount, testDiscardCount, skippedCards);
                //printf("%d pile, %d discard\n", Gcopy.deckCount[p], Gcopy.discardCount[p]);
                int cardDrawn = Gcopy.hand[p][Gcopy.handCount[p]-1];
                if (cardDrawn == copper){
                    treasureFound++;
                    testCoin += 1;
                    testHandCount++;
                }
                else if (cardDrawn == silver){
                    treasureFound++;
                    testCoin += 2;
                    testHandCount++;
                }
                else if (cardDrawn == gold){
                    treasureFound++;
                    testCoin += 3;
                    testHandCount++;
                }
                else {
                    //tbDiscarded[skippedCards] = cardDrawn;
                    Gcopy.handCount[p]--;
                    skippedCards++;
                }

                if (treasureFound == 2)
                    break;
            }
        }

        //Update deck and discard test cases
        testDiscardCount += skippedCards;
        testDeckCount -= (skippedCards + 2);

        cardEffect(card, 0, 0, 0, &G, 0, 0);
        updateCoins(p, &G, 0);

#if (NOISY_TEST == 1)    
    printf("After playing adventurer, player has %d coin(s), %d deckcards, %d discardCards, %d handCards. %d,%d,%d,%d expected.\n", 
        G.coins, G.deckCount[p], G.discardCount[p], G.handCount[p], testCoin, testDeckCount, testDiscardCount, testHandCount);

#endif
    assert(G.coins == testCoin);
    assert(G.deckCount[p] == testDeckCount);
    assert(G.discardCount[p] == testDiscardCount);
    assert(G.handCount[p] == testHandCount);

    }

    printf("All tests passed!\n");
}



int main() {
    srand(time(NULL));
    randomTestAdventurer();
    return 0;
}
